local skynet = require "skynet"
local base = require "base"
local filelog = require "filelog"
local timetool = require "timetool"
local tabletool = require "tabletool"
local msghelper = require "tablehelper"
local math_floor = math.floor
require "fishenum"
local timerfunc = {}
local RETAIN = 10*60

local gamelogic

local Table = {
	table_data = {
		idx = 0,
		seats = {},--座位信息
		waits = {}, --旁观队列 
		state = 0,
		sitdown_player_num = 0, --坐下的玩家数
		conf = nil,
		timer_id = -1,
		--添加桌子的变量
		delete_table_timer_id = -1,
		retain_to_time = 0,    --桌子保留到的时间(linux时间擢)
		gamerecords = {},		--牌桌记录
		roomdiamond = 0,
		roomdiamondwin = 0,
	},

	logic = {	-- 统一管理各种logic，以免模块各自require导致循环溢出。
		tablelogic = require "tablelogic",
		seatlogic = require "seatlogic",
		gamelogic = require "gamelogic",
	},
	retain_to_time = timetool.get_time() + RETAIN,
}

local function do_timer_func(cmd, timer_id, args)
	if type(timerfunc[cmd]) == 'function' then
		timerfunc[cmd](timer_id, args)
	else
		error("Unknown timer function: " .. cmd)
	end
end

local function add_events(name)
	local events = require(name)
	for fn, f in pairs(events) do
		if Table[fn] then
			error("duplicate function: " .. tostring(fn))
		end
		if type(f) == 'function' then
			if fn == "init" then
				f(Table)
			else
				Table[fn] = f
			end
		end
	end
end

-- 从nodecmd的 createtable()里面调用
function Table.start(conf)
	--[[
	skynet.fork(function()
		while true do
			if timetool.get_time() >= Table.retain_to_time then
				if Table.table_data.sitdown_player_num > 0 then
					filelog.warn("force delete table!", timetool.get_time(), Table.retain_to_time)
					Table.leaveallplayers()
				end
			end
			skynet.sleep(10*100)
		end
	end)
	--]]
	return Table.logic.tablelogic.init(Table, conf, FRAME_TIME)
end

function Table.gettableplayer()
	local realplayernum = 0
	if Table.table_data then
		for _, seat in ipairs(Table.table_data.seats or {}) do
			if seat.rid > 100 and not seat.isrobot then
				realplayernum = realplayernum + 1
			end
		end
	end
	return realplayernum
end

function Table.delete()
	local code = Table.table_data.conf.table_code
	--删除桌子前清除桌子的状态
	Table.logic.tablelogic.clear(Table.table_data)
	msghelper:sendmsg_to_roomsvr("delete", code)
end

function Table.kill()
	Table.will_kill = true
	Table.leaveallplayers()
end

function Table.leaveallplayers()
	Table.logic.tablelogic.leaveallplayers(Table.table_data)
end

function Table.exit_service()
	filelog.warn("table is deleted completely!")
	skynet.exit()
end

-- 当玩家在牌桌中时，agent上玩家身上钻石发生改变，要通知游戏
-- value为正 是增加， 负减少
function Table.rid_change_diamond(rid, begindiamond, value, enddiamond)
	if Table.table_data.conf.room_type ~= ERoomType.ROOM_TYPE_COMMON then
		return
	end
	for _, seat in pairs(Table.table_data.seats) do
		if seat.rid == rid then
			local changed = enddiamond - seat.currdiamond
			seat.diamond = seat.diamond + changed
			seat.playerinfo.diamond = seat.diamond
			seat.currdiamond = enddiamond
			msghelper:sendmsg_to_alltableplayer("moneychangeN", {
				money_change_list = {
					{
						rid = rid,
						money_type = 2,
						value = seat.diamond,
					},
				}
			})
			break
		end
	end
end

FRAME_TIME = 0.04	-- 25帧
local prev_update_time

-- not use
local function update()
	if not gamelogic then
        return
    end
	local now_time = skynet.time()
    local interval = now_time - prev_update_time
    if interval < FRAME_TIME then
        skynet.sleep(math_floor(FRAME_TIME - interval)*100)
    end
    prev_update_time = prev_update_time + FRAME_TIME
	local status, msg = pcall(gamelogic.run)
	if not status then
		filelog.sys_error("update pcall error! msg:", msg)
	end
	
    skynet.timeout(0, update)
end

function init()
	timerfunc = require "tabletimer"
	add_events("tablerequest")
	msghelper:init(Table)
	
	gamelogic = Table.logic.gamelogic
	prev_update_time = skynet.time()
	-- skynet.timeout(0, update)
end

local function table_request(f, cmd, ...)
	-- filelog.debug("receive request from agent -> cmd: ", cmd, "args:", ...)
	local status, retmsg = pcall(f, ...)
	if status then
		return retmsg
	else
		filelog.sys_error("call table server: " .. tostring(cmd) .. " failed!", "msg: " .. (retmsg or "nil"))
		return {retcode = EErrCode.ERR_SYSTEM_ERROR, retstr = "系统错误！"}
	end
end

local queue = require "skynet.queue"
local cs = queue()
skynet.start(function()
	skynet.dispatch("lua", function (session, source, cmd, ...)
		-- Table.retain_to_time = timetool.get_time() + RETAIN
		if cmd == "timer" then
			do_timer_func(...)
		else
			local f = Table[cmd]
			if type(f) == 'function' then
				local rsp = cs(table_request, f, cmd, ...)
				skynet.retpack(rsp)
			else
				error("Unknown function request:" .. cmd)
			end
		end
	end)

	init()
end)